﻿using AduSkin.Controls.Metro;
using HsServerHa.Common;
using HsServerHa.Common.Auth;
using HsServerHa.Core.Http;
using HsServerHa.Entity.Models;
using HsServerHa.Utility.DataHelper;
using HsServerHa.Utility.FileHelper;
using HsServerHa.Utility.HttpHelper;
using HsServerHa.Utility.NetWork;
using HsServerHa.Utility.SQLite;
using Newtonsoft.Json;
using Quartz;
using System;
using System.Configuration;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace HsServerHa.Jobs
{
    /// <summary>
    /// 该属性告诉Quartz不要同时执行给定Job定义
    /// </summary>
    [DisallowConcurrentExecution]
    public class CheckXtNumTaskJob : IJob
    {
        public async Task Execute(IJobExecutionContext context)
        {
            #region 授权验证
            if (!AuthorizationVerification.IsVerification())
            {
                return;
            }
           
            #endregion

            try
            {
                if (App.isMaster != null)
                {
                    var list = await SQLiteHelper.TableAsync<VirtuallyManageEntity>().ToListAsync().ConfigureAwait(false);
                    var msFirst = list.FirstOrDefault();
                    if (msFirst == null)
                    {
                        return;
                    }
                    //非主机，并且能够ping通网关，心跳不正常
                    if (!App.isMaster.Value)//非主机
                    {
                        if ((App.IsPingRefer && !NetWorkHelper.IsPingIP(msFirst.VirtuallyIP) && !NetWorkHelper.IsPingIP(App.MasterIP) && !string.IsNullOrEmpty(App.XtIP)))//超时次数大于最大允许超时次数
                        {//这里切换主机
                            Thread.Sleep(5000);//五秒后在检测一遍

                            if ((App.IsPingRefer && !NetWorkHelper.IsPingIP(msFirst.VirtuallyIP) && !NetWorkHelper.IsPingIP(App.MasterIP)))//超时次数大于最大允许超时次数
                            {
                                if ((IniFileConfig.Current.GetStringValue("UserConfig", "IsAutoSwitch") ?? "true").ToBool() == false)
                                {
                                    return;
                                }
                                MasterSlaveSwitchHelper.SwitchMaster();
                                LoggerHelper.SetInfo("心跳正常，参考IP正常，虚拟IP异常，主机IP异常，自动将从机切换成主机", "系统监测");

                                //推送警告
                                await AlarmPushHelper.PushAlarm($"由于{App.CurrIP}心跳正常，参考IP正常，虚拟IP异常，主机IP->{App.MasterIP}异常，自动将从机{App.CurrIP}切换成主机").ConfigureAwait(false);
                                return;
                            }
                        }
                        if (App.XtDisconnectNum > App.MaxXtDisconnectNum && App.IsPingRefer && !NetWorkHelper.IsPingIP(App.MasterIP))
                        {
                            if ((IniFileConfig.Current.GetStringValue("UserConfig", "IsAutoSwitch") ?? "true").ToBool() == false)
                            {
                                return;
                            }
                            MasterSlaveSwitchHelper.SwitchMaster();
                            LoggerHelper.SetInfo("心跳异常，参考IP正常，主机IP异常，自动将从机切换成主机", "系统监测");
                            //推送警告
                            await AlarmPushHelper.PushAlarm($"由于{App.CurrIP}与主机{App.MasterIP}心跳异常，从机参考IP正常，主机IP->{App.MasterIP}异常，自动将从机{App.CurrIP}切换成主机").ConfigureAwait(false);
                            return;
                        }


                        //var dtBind = DbHelperSQLite.Query("select  * from MasterSlaveBind")?.Tables?[0];
                        //var bindList = DataHelpers.ConvertToModel<MasterSlaveBindEntity>(dtBind);

                        var bindList = await SQLiteHelper.TableAsync<MasterSlaveBindEntity>().ToListAsync().ConfigureAwait(false);
                        var bindFirst = bindList?.FirstOrDefault();
                        if (bindFirst == null)
                        {
                            return;
                        }
                        if (NetWorkHelper.IsVirtualIPExists(bindFirst.VirtuallyIP))
                        {
                            NetWorkHelper.DeleteVirtualIP(bindFirst.VirtuallyIP);
                        }

                        //如果参考IP是通的，虚拟IP不通和两服务器都通
                        if (App.IsPingRefer && !NetWorkHelper.IsPingIP(msFirst.VirtuallyIP) && NetWorkHelper.IsPingIP(bindFirst?.MasterIP))
                        {
                            if (bindFirst != null)
                            {
                                //var dtXt = DbHelperSQLite.Query("select * from  HeartManage where IsLocal='true'")?.Tables?[0];
                                //var listXt = DataHelpers.ConvertToModel<HeartEntity>(dtXt);
                                var listXt = await SQLiteHelper.TableAsync<HeartEntity>().Where(x => x.IsLocal == "true").ToListAsync().ConfigureAwait(false);

                                var xtFirst = listXt?.FirstOrDefault();
                                if (xtFirst != null)
                                {
                                    //心跳IPping的通
                                    if (NetWorkHelper.IsPingIP(xtFirst.MasterHeartIPBind))
                                    {
                                        var masterPath = $"http://{bindFirst.MasterIP}:{ConfigurationManager.AppSettings["HttpPort"]?.ToString() ?? "6601"}/";
                                        var result = await HttpHelpers.Get<HttpResponseResultModel<object>>(masterPath +
                                                     (ConfigurationManager.AppSettings["getOppositeServerIsMasterOrSlaveInfo"]?.ToString() ?? "getOppositeServerIsMasterOrSlaveInfo"));
                                        if (result != null)
                                        {
                                            //查询对象是否也是从机
                                            if (!result.IsSuccess)
                                            {
                                                #region 根据双机的时间戳，更新时间比较近的切换为主机
                                                //远程时间戳
                                                var remoteTimeStamp = await GetRemoteSwithHostTimeStamp(bindFirst.SlaveIP);

                                                //本地时间戳
                                                var json = SystemConfigHelper.GetSystemConfig();
                                                var systemInfo = JsonConvert.DeserializeObject<SystemInfo>(json);
                                                long localTimeStamp = 0;
                                                if (systemInfo != null)
                                                {
                                                    localTimeStamp = systemInfo.SwitchHostTimeStamp;
                                                }
                                                //当本地更新时间大于远程更新时间，把本机切换为主机
                                                if (localTimeStamp > remoteTimeStamp)
                                                {                                                   
                                                    if ((IniFileConfig.Current.GetStringValue("UserConfig", "IsAutoSwitch") ?? "true").ToBool() == false)
                                                    {
                                                        return;
                                                    }
                                                    MasterSlaveSwitchHelper.SwitchMaster();
                                                    LoggerHelper.SetInfo("两者都为从，则自动将时间较近的从机切换成主机", "系统监测");
                                                    //推送警告
                                                    await AlarmPushHelper.PushAlarm($"由于两台服务器同时断电或者网络不通，当前两台服务器都为从，自动将IP尾数最小的IP切换为主机").ConfigureAwait(false);
                                                }
                                                #endregion

                                                //    //两者都为从机则比较IP尾数的大小
                                                //    var currList = bindFirst.SlaveIP.Split(".");
                                                //var mstertList = bindFirst.MasterIP.Split(".");

                                                //if (int.Parse(currList[currList.Length - 1]) < int.Parse(mstertList[mstertList.Length - 1]))
                                                //{ //较小的则定义为主机
                                                //    if ((IniFileConfig.Current.GetStringValue("UserConfig", "IsAutoSwitch") ?? "true").ToBool() == false)
                                                //    {
                                                //        return;
                                                //    }
                                                //    MasterSlaveSwitchHelper.SwitchMaster();
                                                //    LoggerHelper.SetInfo("两者都为从，则自动将IP尾数最小的从机切换成主机", "系统监测");
                                                //    //推送警告
                                                //    await AlarmPushHelper.PushAlarm($"由于两台服务器同时断电或者网络不通，当前两台服务器都为从，自动将IP尾数最小的IP切换为主机").ConfigureAwait(false);
                                                //}
                                            }
                                        }
                                    }
                                }
                            }

                        }
                    }
                    else
                    {


                        //如果当前是主机，且参考IP不通，参考IP不为空，心跳IP不为空
                        if (!App.IsPingRefer && !string.IsNullOrEmpty(msFirst.ReferIP) && !string.IsNullOrEmpty(App.XtIP))
                        {
                            Thread.Sleep(5000);
                            //当前为主机,Ping不通网关
                            if (!App.IsPingRefer && App.proxSocket == null && !string.IsNullOrEmpty(App.ReferIP))
                            {
                                if ((IniFileConfig.Current.GetStringValue("UserConfig", "IsAutoSwitch") ?? "true").ToBool() == false)
                                {
                                    return;
                                }
                                MasterSlaveSwitchHelper.SwitchSlave();
                                LoggerHelper.SetInfo("心跳异常，参考IP异常，自动将主机切换成从机", "系统监测");
                            }
                        }

                        var bindList = await SQLiteHelper.TableAsync<MasterSlaveBindEntity>().ToListAsync().ConfigureAwait(false);
                        var bindFirst = bindList?.FirstOrDefault();
                        //如果参考IP是通的，两服务器都通，并且两台服务器都是主机
                        if (App.IsPingRefer && NetWorkHelper.IsPingIP(bindFirst?.SlaveIP))
                        {
                            if (bindFirst != null)
                            {
                                //var dtXt = DbHelperSQLite.Query("select * from  HeartManage where IsLocal='true'")?.Tables?[0];
                                //var listXt = DataHelpers.ConvertToModel<HeartEntity>(dtXt);
                                var listXt = await SQLiteHelper.TableAsync<HeartEntity>().Where(x => x.IsLocal == "true").ToListAsync().ConfigureAwait(false);

                                var xtFirst = listXt?.FirstOrDefault();
                                if (xtFirst != null)
                                {
                                    //心跳IPping的通
                                    if (NetWorkHelper.IsPingIP(xtFirst.MasterHeartIPBind))
                                    {
                                        var masterPath = $"http://{bindFirst.SlaveIP}:{ConfigurationManager.AppSettings["HttpPort"]?.ToString() ?? "6601"}/";
                                        var result = await HttpHelpers.Get<HttpResponseResultModel<object>>(masterPath +
                                                     (ConfigurationManager.AppSettings["getOppositeServerIsMasterOrSlaveInfo"]?.ToString() ?? "getOppositeServerIsMasterOrSlaveInfo"));
                                        if (result != null)
                                        {
                                            //查询对象是否也是主机
                                            if (result.IsSuccess)
                                            {
                                                #region  根据双机时间戳，把比较老的更新时间切为从机
                                                //远程时间戳
                                                var remoteTimeStamp = await GetRemoteSwithHostTimeStamp(bindFirst.SlaveIP);

                                                //本地时间戳
                                                var json = SystemConfigHelper.GetSystemConfig();
                                                var systemInfo = JsonConvert.DeserializeObject<SystemInfo>(json);
                                                long localTimeStamp = 0;
                                                if (systemInfo != null)
                                                {
                                                    localTimeStamp = systemInfo.SwitchHostTimeStamp;
                                                }
                                                //当本地更新时间小于远程更新时间，把本机切换为从机,远程继续保持主机
                                                if (localTimeStamp < remoteTimeStamp)
                                                {
                                                    //较小的则定义为主机
                                                    if ((IniFileConfig.Current.GetStringValue("UserConfig", "IsAutoSwitch") ?? "true").ToBool() == false)
                                                    {
                                                        return;
                                                    }
                                                    MasterSlaveSwitchHelper.SwitchSlave();
                                                    LoggerHelper.SetInfo("两者都为主机，则自动将主机更新时间比较小的服务器切换为从机", "系统监测");
                                                    //推送警告
                                                    await AlarmPushHelper.PushAlarm($"由于两台服务器同时断电或者网络不通，当前两台服务器都为主，自动将最近在线服务器切换为主机").ConfigureAwait(false);
                                                }
                                                #endregion

                                                //两者都为主机则比较IP尾数的大小
                                                //var slaveList = bindFirst.SlaveIP.Split(".");
                                                //var mstertList = bindFirst.MasterIP.Split(".");

                                                //if (int.Parse(slaveList[slaveList.Length - 1]) < int.Parse(mstertList[mstertList.Length - 1]))
                                                //{ //较小的则定义为主机
                                                //    if ((IniFileConfig.Current.GetStringValue("UserConfig", "IsAutoSwitch") ?? "true").ToBool() == false)
                                                //    {
                                                //        return;
                                                //    }
                                                //    MasterSlaveSwitchHelper.SwitchSlave();
                                                //    LoggerHelper.SetInfo("两者都为主机，则自动将IP尾数最大的切换为从机", "系统监测");
                                                //    //推送警告
                                                //    await AlarmPushHelper.PushAlarm($"由于两台服务器同时断电或者网络不通，当前两台服务器都为主，自动将IP尾数最小的IP切换为主机").ConfigureAwait(false);
                                                //}
                                            }
                                        }
                                    }
                                }
                            }

                        }


                        //如果当前是主机，且虚拟IP ping不通
                        if (!string.IsNullOrEmpty(msFirst.VirtuallyIP) && App.IsPingRefer)
                        {
                            Thread.Sleep(10000);
                            if (!NetWorkHelper.IsPingIP(msFirst.VirtuallyIP))
                            {
                                if (msFirst != null)
                                {
                                    //查询当前网卡存不存在虚拟IP ,
                                    var isExist = NetWorkHelper.ValidateIPIsCurrIP(msFirst.VirtuallyIP);
                                    if (!isExist)
                                    {//不存在就增加
                                        int NTEContext = 0;
                                        int NTEInstance;
                                        string virtualIP = msFirst.VirtuallyIP; // 虚拟IP地址
                                        string subnetMask = msFirst.SubnetMask; // 子网掩码
                                        int interfaceIndex = NetWorkHelper.GetInterfaceIndex(msFirst.NetworkCardName); // 网卡接口索引
                                        if (interfaceIndex == -1)
                                        {
                                            LoggerHelper.Error("网卡配置错误");                                         
                                            return;
                                        }

                                        var result = NetWorkHelper.AddVirtualIPAddress((uint)BitConverter.ToInt32(System.Net.IPAddress.Parse(virtualIP).GetAddressBytes(), 0), (uint)BitConverter.ToInt32(System.Net.IPAddress.Parse(subnetMask).GetAddressBytes(), 0), interfaceIndex, out NTEContext, out NTEInstance);
                                        if (result != 0)
                                        {
                                            LoggerHelper.Error("请检查虚拟IP是否合法->" + result);                                         
                                            //推送警告
                                            await AlarmPushHelper.PushAlarm($"当前主机->{App.CurrIP}的虚拟不合法，请重新配置").ConfigureAwait(false);
                                            return;
                                        }
                                        //推送警告
                                        await AlarmPushHelper.PushAlarm($"当前主机->{App.CurrIP}的虚拟IP不通，自动加载了虚拟IP").ConfigureAwait(false);
                                        //修改虚拟表的虚拟KEy
                                        //DbHelperSQLite.ExecuteSql($"update VirtuallyManage set VirtuallyIPKey='{NTEContext}'");

                                        //NetWorkHelper.HandleCMDCommand($"netsh interface ipv4 add address name={msFirst.NetworkCardName} addr={msFirst.VirtuallyIP} mask={msFirst.SubnetMask} gateway={msFirst.Gateway} ");
                                    }

                                    ////刷新网卡
                                    //NetWorkHelper.HandleCMDCommand($"netsh interface set interface {msFirst.NetworkCardName} admin=disable");
                                    //Thread.Sleep(1000);
                                    //NetWorkHelper.HandleCMDCommand($"netsh interface set interface {msFirst.NetworkCardName} admin=enable");

                                    //Thread.Sleep(10000);

                                    //LoggerHelper.SetInfo("当前是主机，虚拟IP异常，刷新网卡，重新加载虚拟IP", "系统监测");
                                }

                            }
                        }

                    }
                }
            }
            catch (System.Exception ex)
            {
                LoggerHelper.Error(ex.Message + ex.ToString());
                LoggerHelper.Error(ex.StackTrace);
            }

        }

        /// <summary>
        /// 获取远程切换主机的时间戳
        /// </summary>
        /// <param name="remoteServer"></param>
        /// <returns></returns>
        public async Task<long> GetRemoteSwithHostTimeStamp(string remoteServer)
        {
            var masterPath = $"http://{remoteServer}:{ConfigurationManager.AppSettings["HttpPort"]?.ToString() ?? "6601"}/";
            var result = await HttpHelpers.Get<HttpResponseResultModel<string>>(masterPath +
                         (ConfigurationManager.AppSettings["getRemoteSystemInfo"]?.ToString() ?? "getRemoteSystemInfo"));

            if (result == null || !result.IsSuccess || result.BackResult == null)
            {
                return 0;
            }
            var systemInfo = JsonConvert.DeserializeObject<SystemInfo>(result.BackResult);
            if (systemInfo == null)
            {
                return 0;
            }
            return systemInfo.SwitchHostTimeStamp;
        }
    }
}